package com.ruoyi.web.controller.api.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.druid.sql.visitor.functions.Now;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.egdk.api.entity.*;
import com.egdk.api.mapp.*;
import com.fasterxml.jackson.annotation.JsonRawValue;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.domain.server.Sys;
import com.ruoyi.system.domain.report.vo.DICOMSeriesImgVo;
import com.ruoyi.system.domain.report.vo.ImagesVo;
import com.ruoyi.system.domain.report.vo.ImgDownDto;
import com.ruoyi.system.domain.report.vo.SeriesVo;
import com.ruoyi.system.mapper.report.PatientMapper;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import sun.misc.BASE64Decoder;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class ApiServiceImpl {


    @Autowired
    private PatientEntityMapper patientEntityMapper;

    @Autowired
    private PtdetailEntityMapper ptdetailEntityMapper;

    @Autowired
    private DICOMSeriesEntityMapper dicomSeriesEntityMapper;

    @Autowired
    private DICOMStudiesEntityMapper dicomStudiesEntityMapper;

    @Autowired
    private DICOMImagesEntityMapper dicomImagesEntityMapper;

    @Autowired
    private TabImagesNEntityMapper tabImagesNEntityMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String DOWNLOAD_DCM = "DOWNLOAD_DCM_";
    private static String CHAR="\r\n";
    public JSONObject getInfo(String accessToken) {
        String objStr = redisTemplate.opsForValue().get(accessToken);
        if (StringUtils.isNotEmpty(objStr)) {
            JSONObject object = JSONObject.parseObject(objStr);
            return object;
        }
        return null;
    }

    public String getIni(String accessToken) {
        String objStr = redisTemplate.opsForValue().get(accessToken);
        if (StringUtils.isNotEmpty(objStr)) {
            JSONObject root = JSONObject.parseObject(objStr);

            JSONObject studyObj=root.getJSONObject("Study");
            StringBuilder builder=new StringBuilder();
            builder.append("[TPatRecord]").append(CHAR);
            builder.append("Pat_PatID").append("=").append(studyObj.getString("PatientID")).append(CHAR);
            builder.append("Stu_StuDes").append("=").append(studyObj.getString("StudyDescription")).append(CHAR);
            builder.append("Pat_PatNam").append("=").append(studyObj.getString("PatientName")).append(CHAR);
            builder.append("Pat_PatSex").append("=").append(studyObj.getString("PatientSex")).append(CHAR);
            builder.append("Pat_PatBirDat").append("=").append(studyObj.getString("PatientBirthDate")).append(CHAR);
            builder.append("Stu_PatAge").append("=").append(studyObj.getString("PatientsAge")).append(CHAR);
            builder.append("Stu_StuDat").append("=").append(studyObj.getString("StudyDate")).append(CHAR);
            builder.append("Stu_StuInsUID").append("=").append(studyObj.getString("StudyInsta")).append(CHAR);
            builder.append("Stu_Priv").append("=").append("").append(CHAR);
            builder.append("Stu_PatSize").append("=").append(studyObj.getString("PatientSize")).append(CHAR);
            builder.append("Institution").append("=").append("").append(CHAR);
            builder.append("Manufacturer").append("=").append(studyObj.getString("Manufacturer")).append(CHAR);
            builder.append("ModelName").append("=").append(studyObj.getString("ModelName")).append(CHAR);
            builder.append("pat_uid").append("=").append(studyObj.getString("pat_uid")).append(CHAR);
            builder.append("pat_mid").append("=").append("").append(CHAR);
            builder.append("pat_name").append("=").append(studyObj.getString("pat_name")).append(CHAR);
            builder.append(CHAR);
            builder.append("iSerCount").append("=").append(studyObj.getString("iSerCount")).append(CHAR);
            builder.append("cBoxWindow").append("=").append(studyObj.getString("cBoxWindow")).append(CHAR);
            builder.append("Server").append("=").append("FUSION_SCREENCAP_A0662").append(CHAR);
            builder.append("ScreenForceTo").append("=").append(studyObj.getString("ScreenForceTo")).append(CHAR);
            builder.append("RegOpenMode").append("=").append("0").append(CHAR);
            builder.append(CHAR);

            JSONArray seriesArray=root.getJSONArray("Series");
            for (int i=0;i<seriesArray.size();i++){
                JSONObject seriesObj=seriesArray.getJSONObject(i);
                builder.append("["+i+"]").append(CHAR);
                builder.append("SerNum").append("=").append(seriesObj.getString("SeriesNumber")).append(CHAR);
                builder.append("Modality").append("=").append(seriesObj.getString("Modality")).append(CHAR);
                builder.append("SerDes").append("=").append(seriesObj.getString("SeriesDescription")).append(CHAR);
                builder.append("BodParExa").append("=").append(seriesObj.getString("BodyPartExamined")).append(CHAR);
                builder.append("SerInsUID").append("=").append(seriesObj.getString("SeriesInst")).append(CHAR);
                builder.append("StuParent").append("=").append(seriesObj.getString("StudyInsta")).append(CHAR);
                builder.append("Manufacturer").append("=").append(seriesObj.getString("Manufacturer")).append(CHAR);
                builder.append("ModelName").append("=").append(seriesObj.getString("ModelName")).append(CHAR);
                builder.append("RadionuclideTotalDose").append("=").append(seriesObj.getString("RadionuclideTotalDose")).append(CHAR);
                builder.append("RadionuclideStartTime").append("=").append(seriesObj.getString("RadionuclideStartTime")).append(CHAR);
                builder.append("NumSerRelIma").append("=").append(seriesObj.getString("NumSerRelIma")).append(CHAR);
                builder.append("iCount").append("=").append(seriesObj.getString("iCount")).append(CHAR);
                builder.append("iFrames").append("=").append(seriesObj.getString("NumFrames")).append(CHAR);
                JSONArray imageArray=seriesObj.getJSONArray("Images");
                for (int k=0;k<imageArray.size();k++){
                    JSONObject imageObj=imageArray.getJSONObject(k);
                    builder.append(k).append("=").append(imageObj.getString("ImageNumber")).append("@").append(imageObj.getString("ImagePositionPatient")).append("@").append("C:\\nanda\\data").append(imageObj.getString("ObjectFile")).append(CHAR);
                }
                builder.append(CHAR);
            }

            return builder.toString();
        }
        return null;
    }

    @Autowired
    private MedicalCaptureMapper medicalCaptureMapper;

    @Value("${nginx.dcm-path}")
    private String dcmPath;

    @Value("${nginx.images-path}")
    private String imagesPath;

    @Value("${MAG0}")
    private String MAG0;

    @Value("${HOST_URL}")
    private String HOST;

    @Value("${CUTIMAGEPATH}")
    private String CUTIMAGEPATH;

    @Value("${IMAGEROOT}")
    private String imageRoot;




    // TODO: 2023/5/13  
    public void handleImageCaptute(MedicalCapture capture) {
        //查询ptdeatilEntity
        PtdetailEntityExample ptdetailExample = new PtdetailEntityExample();
        ptdetailExample.createCriteria().andStudyinstaEqualTo(capture.getStudyinsta());
        List<PtdetailEntity> ptdetailEntities = ptdetailEntityMapper.selectByExample(ptdetailExample);

        //路径生成
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(ptdetailEntities)) {
            PtdetailEntity ptdetail = ptdetailEntities.get(0);
            StringBuilder path = new StringBuilder("/");
            String studyRecordID = String.format("%10s", ptdetail.getPtdeid()).replace(" ", "0");
            String studyCode = String.format("%10s", ptdetail.getPtdtCheckcode()).replace(" ", "0");
            path
                    .append(capture.getStudydate().substring(0,6))
                    .append("/")
                    .append(studyRecordID)
                    .append("_")
                    .append(studyCode)
                    .append("/");
            //文件名
            String ptdtCheckcode = ptdetail.getPtdtCheckcode();
            String fileName =ptdtCheckcode + "_" + UUID.randomUUID().toString().replace("-","");
            String picLast = capture.getPicfile().substring(capture.getPicfile().lastIndexOf('.'), capture.getPicfile().length());
            String dcmLast = capture.getDcmfile().substring(capture.getDcmfile().lastIndexOf('.'), capture.getDcmfile().length());

            //存储过程
            byte[] picBytes = castBase64StrToBytes(capture.getPicstr());
            if (picBytes != null) {
                try {
                    FileUtils.writeByteArrayToFile(new File(CUTIMAGEPATH + imageRoot + path + fileName + picLast), picBytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            byte[] dcmBytes = castBase64StrToBytes(capture.getDcmstr());
            if (dcmBytes != null) {
                try {
                    FileUtils.writeByteArrayToFile(new File(CUTIMAGEPATH + imageRoot + path + fileName + dcmLast), dcmBytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            LocalDateTime now = LocalDateTime.now();
            String date = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            String time = now.format(DateTimeFormatter.ofPattern("HHmmss"));

            TabImagesNEntityWithBLOBs tabImagesNEntityWithBLOBs = new TabImagesNEntityWithBLOBs();
            tabImagesNEntityWithBLOBs.setImPtdtid(Long.valueOf(ptdetail.getPtdeid()));
            tabImagesNEntityWithBLOBs.setImImname(capture.getPicfile());//初始可以就用上传的本来的文件名一致即可
            tabImagesNEntityWithBLOBs.setImSsserial(5);//分组，固定为5
            tabImagesNEntityWithBLOBs.setSequence(2);//序列号，固定为2
            tabImagesNEntityWithBLOBs.setImagedate(date);
            tabImagesNEntityWithBLOBs.setImagetime(time);
            tabImagesNEntityWithBLOBs.setImageGroup("01");
            tabImagesNEntityWithBLOBs.setImauid(capture.getStudyinsta());
            tabImagesNEntityWithBLOBs.setImagePath(path.toString());
            tabImagesNEntityWithBLOBs.setImageName(fileName);
            tabImagesNEntityWithBLOBs.setImageRoot(imageRoot);
            tabImagesNEntityWithBLOBs.setImagedescription(capture.getImadesc());
            tabImagesNEntityWithBLOBs.setImageFormat(capture.getFormat());
            tabImagesNEntityWithBLOBs.setStudyinsta(capture.getStudyinsta());


            tabImagesNEntityMapper.insertSelective(tabImagesNEntityWithBLOBs);
        }else{
            try {
                throw new Exception("无病人数据");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }





    }

    private byte[] castBase64StrToBytes(String base64Str) {
        if (StringUtils.isEmpty(base64Str)) {
            return null;
        }
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] bytes = decoder.decodeBuffer(base64Str);
            return bytes;
        } catch (IOException e) {
            return null;
        }
    }

    public void series(SeriesVo seriesVo) {
        JSONObject object = new JSONObject();

        object.put("function", seriesVo.getFunction());
        object.put("action", seriesVo.getAction());

        //根据SeriesInsta查询Study
        //通过seriesVo的第一个序列的检查ID查询study
        List<DICOMStudiesEntity> studies = dicomStudiesEntityMapper.selectByStudyInsta(seriesVo.getSeries().get(0).getStudyInsta());

        DICOMStudiesEntity studiesEntity = studies.get(0);
        //根据studyInsta查询Ptdetail
        PtdetailEntityExample ptdetailExample = new PtdetailEntityExample();
        ptdetailExample.createCriteria().andStudyinstaEqualTo(studiesEntity.getStudyinsta());
        List<PtdetailEntity> ptdetailEntities = ptdetailEntityMapper.selectByExample(ptdetailExample);

        //装载Study数据
        JSONObject studyObj = new JSONObject();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(ptdetailEntities)) {
            PtdetailEntity ptdetail = ptdetailEntities.get(0);
            Integer patientId = ptdetail.getPtdtPatientid();

            //根据patientId查询PatientEntity
            PatientEntityExample patientExample = new PatientEntityExample();
            patientExample.createCriteria().andPatientidEqualTo(patientId);
            List<PatientEntity> patientEntities = patientEntityMapper.selectByExample(patientExample);
            PatientEntity patientEntity = patientEntities.get(0);

            studyObj.put("pat_mid", patientEntity.getPtMid());
            studyObj.put("pat_uid", patientEntity.getPtUid());
            studyObj.put("pat_name", patientEntity.getPtName());
        }

        studyObj.put("PatientID", studiesEntity.getPatientid());
        studyObj.put("StudyDescription", studiesEntity.getStudydescription());
        studyObj.put("PatientName", studiesEntity.getPatientname());
        studyObj.put("PatientSex", studiesEntity.getPatientsex());
        studyObj.put("PatientBirthDate", studiesEntity.getPatientbirthdate());
        studyObj.put("PatientsAge", studiesEntity.getPatientsage());
        studyObj.put("StudyDate", studiesEntity.getStudydate());
        studyObj.put("StudyInsta", studiesEntity.getStudyinsta());
        studyObj.put("PatientSize", studiesEntity.getPatientsize());
        studyObj.put("Institution", studiesEntity.getInstitutionname());
        studyObj.put("Manufacturer", studiesEntity.getManufacturer());
        studyObj.put("ModelName", studiesEntity.getModelname());
        studyObj.put("iSerCount", seriesVo.getSeries().size());
        studyObj.put("cBoxWindow", "0");
        studyObj.put("ScreenForceTo", "0");
        studyObj.put("Server", "");
        studyObj.put("Client", "");
        object.put("Study", studyObj);

        JSONArray seriesArr = new JSONArray();
        for (DICOMSeriesImgVo serie : seriesVo.getSeries()) {

            //装载Series数据
            JSONObject seriesObj = new JSONObject();

            seriesObj.put("SeriesNumber", serie.getSeriesNumber());
            seriesObj.put("Modality", serie.getModality());
            seriesObj.put("SeriesDescription", serie.getSeriesDescription());
            seriesObj.put("BodyPartExamined", serie.getBodyPartExamined());
            seriesObj.put("SeriesInst", serie.getSeriesInst());
            seriesObj.put("StudyInsta", serie.getStudyInsta());
            seriesObj.put("Manufacturer", serie.getManufacturer());
            seriesObj.put("ModelName", serie.getModelName());
            seriesObj.put("SeriesDate", serie.getSeriesDate());
            seriesObj.put("SeriesTime", serie.getSeriesTime());
            seriesObj.put("RadionuclideTotalDose", serie.getRadionuclideTotalDose());
            seriesObj.put("RadionuclideStartTime", serie.getRadionuclideStartTime());
            seriesObj.put("NumSerRelIma", serie.getNumSerRelIma());
            seriesObj.put("NumFrames", serie.getNumFrames());
            //装载图像数据
            List<DICOMImagesEntity> dicomImages = new ArrayList<>();
            if (Objects.equals(serie.getNumFrames(), serie.getNumSerRelIma())) {
                dicomImages = dicomImagesEntityMapper.selectDicomImageWhenEqual(serie.getSeriesInst());
            } else {
                dicomImages = dicomImagesEntityMapper.selectDicomImageWhenNotEqual(serie.getSeriesInst());
            }

            if (CollUtil.isNotEmpty(dicomImages)) {
                seriesObj.put("PixelSpacing", dicomImages.stream().map(DICOMImagesEntity::getPixelspacing).findFirst().get());

                Integer iCount = 0;
                JSONArray imageArr = new JSONArray();
                for (DICOMImagesEntity image : dicomImages) {
                    JSONObject imageObj = new JSONObject();
                    imageObj.put("ImageNumber", image.getImagenumber());
                    imageObj.put("ImagePositionPatient", image.getImagepositionpatient());
                    String uuid = DOWNLOAD_DCM + UUID.randomUUID().toString().replaceAll("-", "");
                    imageObj.put("Root", HOST + uuid);

                    //缓存到redis，设置缓存时间为1小时
                    imageObj.put("ObjectFile", image.getObjectfile());
                    if (image.getDevicename().equalsIgnoreCase("MAG0")) {
                        String dcmPath = MAG0 + image.getObjectfile();
                        if (FileUtil.exist(new File(dcmPath))) {
                            iCount++;
                            String objectFile=image.getObjectfile();
                            //文件名
                            String diskfilename = objectFile.substring(objectFile.lastIndexOf("\\")+1, objectFile.length());
                            //设置文件路径,并缓存到redis，设置缓存时间为1小时
                            redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(new ImgDownDto(dcmPath, "1", diskfilename)), 1, TimeUnit.HOURS);
                        }

                    }
                    imageArr.add(imageObj);
                }
                seriesObj.put("iCount", iCount);

                seriesObj.put("Images", imageArr);
            }
            seriesArr.add(seriesObj);
        }
        object.put("Series", seriesArr);
        //设置accessToken返回数据
        redisTemplate.opsForValue().set(seriesVo.getUuid(), object.toJSONString(), 10, TimeUnit.MINUTES);
    }


    public void downloadDcm(String uuid, HttpServletResponse response) {
        String val = redisTemplate.opsForValue().get(uuid);
        if (StringUtils.isEmpty(val)) {

            response.setHeader("Etag", "W/\"9767057-1323779115364\"");
            response.addHeader("status", "invalid");
            writeOutStream(response, null);
        } else {
            ImgDownDto imgdown = JSONObject.parseObject(val, ImgDownDto.class);
            String diskfilename = imgdown.getDiskfilename();

            if ("1".equalsIgnoreCase(imgdown.getType())) {
                String path = imgdown.getPath();
                try {
                    byte[] data = IOUtils.toByteArray(new FileInputStream(new File(path)));
                    String type = new MimetypesFileTypeMap().getContentType(new File(path));

                    //设置header
                    response.setContentType(type);
                    response.setHeader("Content-Disposition", "attachment; filename=\"" + diskfilename + "\"");
                    response.setContentLength(data.length);
                    response.setHeader("Content-Range", "" + (data.length - 1));
                    response.setHeader("Accept-Ranges", "bytes");

                    writeOutStream(response, data);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }

    private void writeOutStream(HttpServletResponse response, byte[] bytes) {
        try {
            OutputStream os = response.getOutputStream();
            if (bytes != null) {
                os.write(bytes);
            }
            //先声明的流后关掉！
            os.flush();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    public AjaxResult getImage(String studyInsta) {
        TabImagesNEntityExample tabImagesNEntityExample = new TabImagesNEntityExample();
        tabImagesNEntityExample.createCriteria().andStudyinstaEqualTo(studyInsta);
        List<TabImagesNEntity> tabImagesNEntities = tabImagesNEntityMapper.selectByExample(tabImagesNEntityExample);

        ArrayList<String> imagesVos = new ArrayList<String>();
        if (ObjectUtil.isNotEmpty(tabImagesNEntities)){
            for (TabImagesNEntity t:tabImagesNEntities){
                String imageRoot1 = t.getImageRoot();
                String imagePath = t.getImagePath();
                String imageName = t.getImageName();
                String imageFormat = t.getImageFormat();
                String completePath = imageRoot1 + imagePath + imageName + "." + imageFormat;
                imagesVos.add(completePath);
            }
            return AjaxResult.success(imagesVos);
        }

        return AjaxResult.success("没有相关路径");
    }


}
